跳到主要内容

SpringBoot 使用 Redis 实现 Session 共享

什么是 Session

参考资料 SpringBoot 使用 Redis 实现 Session 共享

学习 HTTP 协议时多少已经了解为什么需要使用 Session 就是为了维持状态,但是到了现在这种各种分布式的时代单机的 Session 就不太够用了,因为一个用户的请求可能需要用到多个服务器,所以相应的用户的 Session 也需要多份,所以需要同步 Session

目前主流的分布式 Session 管理有两种方案

Session 复制和 Session 集中存储

一般不使用第一种方式,维护成本太高了,大部分情况都是在单独的服务器或服务器集群上使用缓存技术,如 Redis 存储 Session 数据,集中管理所有的 Session,所有的 Web 服务器都从这个存储介质中存取对应的 Session,实现 Session 共享

将 Session 信息从应用中剥离出来后,其实就达到了服务的无状态化,这样就方便在业务极速发展时水平扩充。

注:使用方式还是和学习 JavaService 那时的一样,使用 Session 作用域保存数据而已

// 当时学习 JavaService 时的用法
HttpSession session = request.getSession();
session.setAttribute("username", username);

Redis 缓存状态

参考资料 Spring Boot (五): Redis缓存使用姿势盘点

Spring Session 提供了一套创建和管理 Servlet HttpSession 的方案。

Spring Session 提供了集群 Session(Clustered Sessions)功能,默认采用外置的 Redis 来存储 Session 数据,以此来解决 Session 共享的问题。

配合 Redis 使用(Redis 的配置在上面)

<!-- https://mvnrepository.com/artifact/org.springframework.session/spring-session-data-redis -->
<!-- 只需导入这个包就好了,SpringBoot 默认的 Session 管理就是这个 -->
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
<version>2.3.0.RELEASE</version>
</dependency>
@SpringBootApplication
@EnableCaching
// maxInactiveIntervalInSeconds: 设置 Session 失效时间
// 使用 Redis Session 之后,原 Spring Boot 中的 server.session.timeout 属性不再生效
@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 1800)
public class SpringBootRedisApplication {

public static void main(String[] args) {
SpringApplication.run(SpringBootRedisApplication.class, args);
}

}

使用 Session 的方式

使用方式和 JavaService 包下的 HttpSession 用法基本一致

@RequestMapping(value = "/setSession")
public Map<String, Object> setSession (HttpServletRequest request){
Map<String, Object> map = new HashMap<>();
request.getSession().setAttribute("message", request.getRequestURL());
map.put("request Url", request.getRequestURL());
return map;
}

@RequestMapping(value = "/getSession")
public Object getSession (HttpServletRequest request){
Map<String, Object> map = new HashMap<>();
map.put("sessionId", request.getSession().getId());
map.put("message", request.getSession().getAttribute("message"));
return map;
}

@RequestMapping(value = "/login")
public String login (HttpServletRequest request,String userName,String password){
String msg="logon failure!";
if (userName!=null && "admin".equals(userName) && "123".equals(password)){
request.getSession().setAttribute("user",userName);
msg="login successful!";
}
return msg;
}
# 先访问 
http://localhost:8080/hello/setSession

# 在访问这个,如果能取得数据表示配置成功
http://localhost:8080/hello/getSession